#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "EnemyManager.h"
#include "vec3f.h"

using namespace std;

// Constructor
EnemyManager::EnemyManager(){
	fTimer = 1.75f;
	fTimerReset = 1.75f;
	fMaxWidth = 30;
	fMaxHeight = -19.0f;
	iLevel = 1;
	iDirection = 1;  // Default direction is right	
	srand ((unsigned) time(0) );
}
		
// Main Functions	
void EnemyManager::Initialize(){

	// Clear 
	myEnemiesA.clear();
	myEnemiesB.clear();
	myEnemiesC.clear();
	myEnemiesD.clear();
	myEnemiesE.clear();

	// Create
	float unitsX = 5.0f;
	float unitsY = 3.0f;
	float startLeft = -22.0f;
	float startTop = 20.0f;

	for (int i = 0;i<10;i++)
	{
		Enemy *temp = new Enemy();
		Enemy *temp2 = new Enemy();
		Enemy *temp3 = new Enemy();
		Enemy *temp4 = new Enemy();
		Enemy *temp5 = new Enemy();
		temp->SetTranslation(new Vec3f(startLeft+unitsX*i,startTop,0.0f));
		temp2->SetTranslation(new Vec3f(startLeft+unitsX*i,startTop-unitsY,0.0f));
		temp3->SetTranslation(new Vec3f(startLeft+unitsX*i,startTop-unitsY*2,0.0f));
		temp4->SetTranslation(new Vec3f(startLeft+unitsX*i,startTop-unitsY*3,0.0f));
		temp5->SetTranslation(new Vec3f(startLeft+unitsX*i,startTop-unitsY*4,0.0f));
		myEnemiesA.push_back(*temp);
		myEnemiesB.push_back(*temp2);
		myEnemiesC.push_back(*temp3);
		myEnemiesD.push_back(*temp4);
		myEnemiesE.push_back(*temp5);
	}
}
Bullet EnemyManager::Update(float deltaTime){
		fTimer -= deltaTime/1000;
		if (fTimer<=0){
			   fTimer = fTimerReset;
			   // Check border && update new Direction
			   CheckBorder();

			   // Set Direction of Enemies
			   UpdateHelper(deltaTime);
		}

		// Determine which enemies shoot bullets
		Bullet* theBullet = new Bullet();
		theBullet->Initialize(new Vec3f(0.0f,100.0f,0.0f));
		theBullet->SetDirection(-1);
		int iSecret = rand() % 25 + 1;
		
		if (iSecret == 1){
			printf("Bullet Shot");
			vector <Vec3f> tempBulletOrigin;
			for (int i = 0;i<myEnemiesA.size();i++){
				Vec3f* tempPosition = new Vec3f(myEnemiesA.at(i).GetTranslation().v[0],
												myEnemiesA.at(i).GetTranslation().v[1]-2.0f,
												0.0f);
				tempBulletOrigin.push_back(*tempPosition);
			}
			for (int i = 0;i<myEnemiesB.size();i++){
				Vec3f* tempPosition = new Vec3f(myEnemiesB.at(i).GetTranslation().v[0],
												myEnemiesB.at(i).GetTranslation().v[1]-2.0f,
												0.0f);
				tempBulletOrigin.push_back(*tempPosition);
			}
			for (int i = 0;i<myEnemiesC.size();i++){
				Vec3f* tempPosition = new Vec3f(myEnemiesC.at(i).GetTranslation().v[0],
												myEnemiesC.at(i).GetTranslation().v[1]-2.0f,
												0.0f);
				tempBulletOrigin.push_back(*tempPosition);
			}
			for (int i = 0;i<myEnemiesD.size();i++){
				Vec3f* tempPosition = new Vec3f(myEnemiesD.at(i).GetTranslation().v[0],
												myEnemiesD.at(i).GetTranslation().v[1]-2.0f,
												0.0f);
				tempBulletOrigin.push_back(*tempPosition);
			}
			for (int i = 0;i<myEnemiesE.size();i++){
				Vec3f* tempPosition = new Vec3f(myEnemiesE.at(i).GetTranslation().v[0],
												myEnemiesE.at(i).GetTranslation().v[1]-2.0f,
												0.0f);
				tempBulletOrigin.push_back(*tempPosition);
			}
			int iPos = rand() % tempBulletOrigin.size();
			theBullet->Initialize(new Vec3f(tempBulletOrigin.at(iPos).v[0],tempBulletOrigin.at(iPos).v[1],0.0f));

		}

		// Check if all enemies are dead
		if (myEnemiesA.size() == 0 && myEnemiesB.size() == 0 &&
		myEnemiesC.size() == 0 && myEnemiesD.size() == 0 && myEnemiesE.size()== 0 ){
			   EnemyManager::Initialize();
			   iLevel++;
		}
	return *theBullet;
}

void EnemyManager::Draw(){

	for (int i = 0;i<myEnemiesA.size();i++){
		myEnemiesA.at(i).Draw();
	}
	for (int i = 0;i<myEnemiesB.size();i++){
		myEnemiesB.at(i).Draw();
	}
	for (int i = 0;i<myEnemiesC.size();i++){
		myEnemiesC.at(i).Draw();
	}
	for (int i = 0;i<myEnemiesD.size();i++){
		myEnemiesD.at(i).Draw();
	}
	for (int i = 0;i<myEnemiesE.size();i++){
		myEnemiesE.at(i).Draw();
	}
}
bool EnemyManager::IsEmpty(){
	return (myEnemiesA.size()<=0&&myEnemiesB.size()<=0&&myEnemiesC.size()<=0&&myEnemiesD.size()<=0&&myEnemiesE.size()<=0);
}

void EnemyManager::UpdateHelper(float deltaTime){

	for (int i = 0;i<myEnemiesA.size();i++){
		myEnemiesA.at(i).SetDirection(iDirection);
		myEnemiesA.at(i).Update(deltaTime);
	}
	for (int i = 0;i<myEnemiesB.size();i++){
		myEnemiesB.at(i).SetDirection(iDirection);
		myEnemiesB.at(i).Update(deltaTime);
	}
	for (int i = 0;i<myEnemiesC.size();i++){
		myEnemiesC.at(i).SetDirection(iDirection);
		myEnemiesC.at(i).Update(deltaTime);
	}
	for (int i = 0;i<myEnemiesD.size();i++){
		myEnemiesD.at(i).SetDirection(iDirection);
		myEnemiesD.at(i).Update(deltaTime);
	}
	for (int i = 0;i<myEnemiesE.size();i++){
		myEnemiesE.at(i).SetDirection(iDirection);
		myEnemiesE.at(i).Update(deltaTime);
	}
	if (iDirection == 0)
		iDirection = iPrevious;
}

void EnemyManager::CheckBorder(){

	vector <Enemy> vTempEnemies;
	if (iDirection > 0 ){// Check Right Border
		// Add all Enemy Objects farthest right on each row to the temporary vector
		if (myEnemiesA.size() >0)
			vTempEnemies.push_back(myEnemiesA.at(myEnemiesA.size()-1));
		if (myEnemiesB.size() >0)
			vTempEnemies.push_back(myEnemiesB.at(myEnemiesB.size()-1));
		if (myEnemiesC.size() >0)
			vTempEnemies.push_back(myEnemiesC.at(myEnemiesC.size()-1));
		if (myEnemiesD.size() >0)
			vTempEnemies.push_back(myEnemiesD.at(myEnemiesD.size()-1));
		if (myEnemiesE.size() >0)
			vTempEnemies.push_back(myEnemiesE.at(myEnemiesE.size()-1));

		// Check the objects if they breached the border
		bool bReachedBorder = false;
		for (int i = 0; i<vTempEnemies.size();i++){
			if (vTempEnemies.at(i).GetTranslation().v[0] > fMaxWidth)
				bReachedBorder = true;
		}
		if (bReachedBorder){ // Breached border
			iDirection *= -1;
			MoveDown();
		}		
	}

	else if (iDirection < 0 )// Check Left Border
	{
		// Add all Enemy Objects farthest left on each row to the temporary vector
		if (myEnemiesA.size() >0)
			vTempEnemies.push_back(myEnemiesA.at(0));
		if (myEnemiesB.size() >0)
			vTempEnemies.push_back(myEnemiesB.at(0));
		if (myEnemiesC.size() >0)
			vTempEnemies.push_back(myEnemiesC.at(0));
		if (myEnemiesD.size() >0)
			vTempEnemies.push_back(myEnemiesD.at(0));
		if (myEnemiesE.size() >0)
			vTempEnemies.push_back(myEnemiesE.at(0));

		// Check the objects if they breached the border
		bool bReachedBorder = false;
		for (int i = 0; i<vTempEnemies.size();i++){
			if (vTempEnemies.at(i).GetTranslation().v[0] < -1*fMaxWidth)
				bReachedBorder = true;
		}
		if (bReachedBorder){ // Breached border
			iDirection *= -1;
			MoveDown();
		}
	}
}

void EnemyManager::MoveDown(){
	bool bBorderBottom = false;
	Enemy* tempEnemy = new Enemy();
	float fMove = 3.0f;

	// Check whether at bottom border
	if (myEnemiesE.size() >0)
		tempEnemy = &myEnemiesE.at(0);
	else if (myEnemiesD.size() >0)
		tempEnemy = &myEnemiesD.at(0);
	else if (myEnemiesC.size() >0)
		tempEnemy = &myEnemiesC.at(0);
	else if (myEnemiesB.size() >0)
		tempEnemy = &myEnemiesB.at(0);
	else if (myEnemiesA.size() >0)
		tempEnemy = &myEnemiesA.at(0);
	if (tempEnemy != NULL && tempEnemy->GetTranslation().v[1]<=fMaxHeight){
		bBorderBottom = true;
	}

	// Move Down
	if (!bBorderBottom){
		
		for (int i = 0;i<myEnemiesA.size();i++){
			myEnemiesA.at(i).MoveDown(fMove);
		}
		for (int i = 0;i<myEnemiesB.size();i++){
			myEnemiesB.at(i).MoveDown(fMove);
		}
		for (int i = 0;i<myEnemiesC.size();i++){
			myEnemiesC.at(i).MoveDown(fMove);
		}
		for (int i = 0;i<myEnemiesD.size();i++){
			myEnemiesD.at(i).MoveDown(fMove);
		}
		for (int i = 0;i<myEnemiesE.size();i++){
			myEnemiesE.at(i).MoveDown(fMove);
		}
		iPrevious = iDirection;
		iDirection = 0;
	}
}